package com.project.demo.util;

import com.alibaba.fastjson.JSONObject;
import org.apache.commons.httpclient.HttpStatus;
import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.net.ssl.SSLContext;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.util.ArrayList;
import java.util.Map;


public class HttpClientUtils {
	private static Logger logger = LoggerFactory.getLogger(HttpClientUtils.class); // 日志记录

	private static RequestConfig requestConfig = null;

	static {
		// 设置请求和传输超时时间
		requestConfig = RequestConfig.custom().setSocketTimeout(60000).setConnectTimeout(60000).build();
	}

	/**
	 * post请求传输json参数
	 *
	 * @param url       url地址
	 * @param jsonParam 参数
	 * @return
	 */
	public static String httpPost(String url, String jsonParam) {
		logger.info("post请求传输json参数 开始，url:{}, 参数：{}", url, jsonParam);
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// post请求返回结果
		String str = null;
		HttpPost httpPost = new HttpPost(url);
		// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam, "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			// 请求发送成功，并得到响应
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				try {
					// 读取服务器返回过来的json字符串数据
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					logger.info("服务器返回过来的json字符串数据:{}", str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return str;
	}

	/**
	 * post表单提交
	 *
	 * @param url
	 * @param map
	 * @return
	 */
	public static String httpPost(String url, Map<String, String> map) {
		logger.info("post请求传输json参数 开始，url:{}, 参数：{}", url, null == map ? null : map.toString());
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// 创建表单
		HttpPost httpPost = new HttpPost(url);
		// 用于存放表单数据.
		ArrayList<BasicNameValuePair> pairs = new ArrayList<>();
		//遍历map 将其中的数据转化为表单数据
		for (Map.Entry<String, String> entry : map.entrySet()) {
			logger.info("key: {}", entry.getKey());
			logger.info("value: {}", entry.getValue());
			pairs.add(new BasicNameValuePair(entry.getKey(), entry.getValue()));
		}
		// post请求返回结果
		String str = null;
		try {
			// 解决中文乱码问题
			httpPost.setEntity(new UrlEncodedFormEntity(pairs, "utf-8"));

			CloseableHttpResponse result = httpClient.execute(httpPost);
			// 请求发送成功，并得到响应
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				try {
					// 读取服务器返回过来的json字符串数据
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					logger.info("服务器返回过来的json字符串数据:{}", str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (Exception e) {
			logger.error("post请求提交失败：" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return str;

	}


	/**
	 * post请求传输json参数
	 *
	 * @param url       url地址
	 * @param jsonParam 参数
	 * @param headers   请求头
	 * @return
	 */
	public static JSONObject httpPost(String url, String jsonParam, Header... headers) {
		logger.info("post请求传输json参数 开始，url:{}, 参数：{}", url, null == jsonParam ? null : jsonParam);
		CloseableHttpClient httpClient = HttpClients.createDefault();
		// post请求返回结果
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);
		// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		try {
			if (null != jsonParam) {
				// 解决中文乱码问题
				StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
				entity.setContentEncoding("UTF-8");
				entity.setContentType("application/json");
				httpPost.setEntity(entity);
			}
			if (headers != null) {
				for (Header header : headers) {
					httpPost.addHeader(header);
				}
			}
			CloseableHttpResponse result = httpClient.execute(httpPost);
			// 请求发送成功，并得到响应
			if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				String str = "";
				try {
					// 读取服务器返回过来的json字符串数据
					str = EntityUtils.toString(result.getEntity(), "utf-8");
					logger.info("服务器返回过来的json字符串数据:{}", str);
					// 把json字符串转换成json对象
					jsonResult = JSONObject.parseObject(str);
				} catch (Exception e) {
					logger.error("post请求提交失败:" + url, e);
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}

	/**
	 * post请求传输json参数
	 *
	 * @param url       url地址
	 * @param jsonParam 参数
	 * @param headers   请求头
	 * @return
	 */
	public static JSONObject httpsPost(String url, String jsonParam, Header... headers) throws KeyManagementException, NoSuchAlgorithmException {
		logger.info("post请求传输json参数 开始，url:{}, 参数：{}", url, null == jsonParam ? null : jsonParam);

		// post请求返回结果
		JSONObject jsonResult = null;
		HttpPost httpPost = new HttpPost(url);

		// 设置请求和传输超时时间
		httpPost.setConfig(requestConfig);
		try {
			if (url.contains("https")) {
				SSLContext sslContext = null;
				sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
					@Override
					public boolean isTrusted(X509Certificate[] chain, String authType) throws CertificateException {
						return true;
					}
				}).build();
				SSLConnectionSocketFactory sslsf = new SSLConnectionSocketFactory(sslContext, NoopHostnameVerifier.INSTANCE);
				// 创建自定义的 HttpClient，将 SSLContext 应用于它
				CloseableHttpClient httpClient = HttpClients.custom()
						.setSSLSocketFactory(sslsf)
						.build();

				if (null != jsonParam) {
					// 解决中文乱码问题
					StringEntity entity = new StringEntity(jsonParam.toString(), "utf-8");
					entity.setContentEncoding("UTF-8");
					entity.setContentType("application/json");
					httpPost.setEntity(entity);
				}
				if (headers != null) {
					for (Header header : headers) {
						httpPost.addHeader(header);
					}
				}
				CloseableHttpResponse result = httpClient.execute(httpPost);
				// 请求发送成功，并得到响应
				if (result.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
					String str = "";
					try {
						// 读取服务器返回过来的json字符串数据
						str = EntityUtils.toString(result.getEntity(), "utf-8");
						logger.info("服务器返回过来的json字符串数据:{}", str);
						// 把json字符串转换成json对象
						jsonResult = JSONObject.parseObject(str);
					} catch (Exception e) {
						logger.error("post请求提交失败:" + url, e);
					}
				}
			}
		} catch (IOException e) {
			logger.error("post请求提交失败:" + url, e);
		} catch (KeyStoreException e) {
			throw new RuntimeException(e);
		} finally {
			httpPost.releaseConnection();
		}
		return jsonResult;
	}


	/**
	 * 发送get请求
	 *
	 * @param url 路径
	 * @return
	 */
	public static JSONObject httpGet(String url) {
		// get请求返回结果
		logger.info("http get请求，url:{}", url);
		JSONObject jsonResult = null;
		CloseableHttpClient client = HttpClients.createDefault();
		// 发送get请求
		HttpGet request = new HttpGet(url);
		request.setConfig(requestConfig);
		try {
			CloseableHttpResponse response = client.execute(request);

			// 请求发送成功，并得到响应
			if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
				// 读取服务器返回过来的json字符串数据
				HttpEntity entity = response.getEntity();
				String strResult = EntityUtils.toString(entity, "utf-8");
				logger.info("服务器返回过来的json字符串数据:{}", strResult);
				// 把json字符串转换成json对象
				jsonResult = JSONObject.parseObject(strResult);
			} else {
				logger.error("get请求提交失败:" + url);
			}
		} catch (IOException e) {
			logger.error("get请求提交失败:" + url, e);
		} finally {
			request.releaseConnection();
		}
		return jsonResult;
	}

}
